/**
 * 趁着还能看懂，写一点注释 2013-08-22 by allanz
 * 
 * 这是ajaxMenu这个组件的js支持部分，使用qtip实现一个层级式的下拉菜单，数据由页面上的ajaxMenuDataProvider提供，实际上是一个jsFunction
 * 
 */
aicommon.jsf.ajaxMenu = {};

//缓存菜单数据，多个输入框使用相同的菜单数据提供者的时候，
//各层级的数据分别只请求一次
aicommon.jsf.ajaxMenu.dataPool = {
	__options : {}
};

//对外公开的方法，在输入框上的onfocus事件上调用
//root是菜单数据的key，会传递给后台的数据提供者
//dataProvider是提供数据的js函数的名称
aicommon.jsf.ajaxMenu.show = function(event,element,options){
	var root = options.root;
	var trigger = options.trigger || "click";
	var position = options.position || "bottomLeft";
	var dataProvider = options.dataProvider;
	
	element = $j(element);
	//目标元素的onmouseover或者onmouseenter事件上调用本方法，多次调用的时候靠menuinited属性的值来判断，阻止重复初始化
	if(element.attr("menuinited") == "true")return;
	else element.attr("menuinited","true");
	
	aicommon.jsf.ajaxMenu.createMenu(element,{
		trigger : trigger,
		tipContent : aicommon.jsf.ajaxMenu.createLoading({id:element.attr("id") + "_submenus",styleClass : options.styleClass}),
		position : position
	});
	
	//dataProvider的名字记录在了元素上，多有妙用
	element.attr("dataProvider",dataProvider);
	
	//先从缓存中去菜单数据
	var cachedData = aicommon.jsf.ajaxMenu.dataPool[dataProvider];
	if(cachedData == null){
		cachedData = {};
		aicommon.jsf.ajaxMenu.dataPool[dataProvider] = cachedData;
	}
	
	aicommon.jsf.ajaxMenu.dataPool.__options[dataProvider] = options;
	
	if(cachedData[root] == null) //缓存中没有，那么调用dataProvider去加载数据，加载完之后会调用replaceSubMenuContent
		window[dataProvider](root,element.attr("id"));
	else	//缓存中有数据，那么就直接使用这个数据来更新菜单
		aicommon.jsf.ajaxMenu.replaceSubMenuContent(element.attr("id"),
				cachedData[root]);
	
	//非ie下要调用一下展现
	if(!$j.browser.msie)
		element.qtip("api").show(event);
};

//创建菜单，会在每一级菜单数据加载后执行
aicommon.jsf.ajaxMenu.createMenu = function(element,options){
	var triggerType = options.trigger;
	var position = options.position;
	var tipContent = options.tipContent;
	
	var menuPosition = {
        adjust: {
           screen: true, // Keep the tooltip on-screen at all times
           mouse : false
        }
	} ;
	
	if(position == "mouse")
		menuPosition.target = "mouse";
	else
		menuPosition.corner = {target: position};
	
	$j(element).qtip({
		content : {
			text : tipContent,
			prerender : true
		},
		position : menuPosition,
		show : {
			delay : 0,
			when : triggerType,
			effect: { type: '1',length : 0 }//不适用任何特殊效果，直接show展现
		},
		hide : {
			delay : 0,
			when : "unfocus",
			effect: { type: '11',length : 0 }//不适用任何特殊效果，直接hide
		},
		style : {
			tip : false
		},
		api : {
			onShow : function(){
				var menuItems = this.elements.tooltip.find("li");
				
				//计算高度
				menuItems.each(function(index,item){
					item = $j(item);
					var contentHeight = item.find("div.menuMask").height();
					item.css("height",(contentHeight + 8) + "px");
				});
			},
			beforeShow : function(event){
				if(this.elements.target.hasClass("disabled"))
					return false;
				
				//shit!!!
				if($j.browser.msie && this.elements.tooltip.outerWidth() < 10){
					this.elements.tooltip.find("div.qtip-contentWrapper,div.qtip-content")
						.css("width","168px");
					this.elements.tooltip.find("div.qtip-wrapper").css("width","175px");
				}
				
				this.cache.mouse = { x: event.pageX, y: event.pageY };
				//展现前清除样式，并且要把新展现的菜单置于最上一层
				this.elements.content.find("li").removeClass("current").removeClass("disabledCurrent");
				var maxIndex = 0;
				var maxIndexElement;
				$j("div.qtip[qtip]").each(function(){
					var t = $j(this).css("z-index");
					if(t == null || t == "")t = 0;
					else t = parseInt(t);
					if(maxIndex < t){
						maxIndex = t;
						maxIndexElement = this;
					};
				});

				if(maxIndexElement != null && this.elements.tooltip[0] != maxIndexElement)
					this.elements.tooltip.css("z-index",maxIndex + 1);
				else if(this.elements.tooltip.css("z-index") == "auto"
					|| this.elements.tooltip.css("z-index") == "0")
					this.elements.tooltip.css("z-index",500);
				
				var menuItems = this.elements.tooltip.find("li");
				
				menuItems.trigger("show");
				
				var dataProvider = $j("#" + this.elements.target.attr("root")).attr("dataProvider");
				var options = aicommon.jsf.ajaxMenu.dataPool.__options[dataProvider];
				
				if(options){
					var maxRows = options.maxRows;
	
					if(maxRows != null && menuItems.length > 0){
						maxRows = parseInt(maxRows);
						var width = Math.ceil(menuItems.length/maxRows)*170;
						this.elements.tooltip.find("div.qtip-wrapper").css("width",width);
						this.elements.tooltip.find("ul li")
							.css("border-left","1px solid #CCC")
							.css("float","left")
							.find("div.menuMask").css("left","10px");
					}
					
					if(options.beforeShow)
						options.beforeShow.bind(this).call(event);
				}
			},
			beforeHide : function(event){
				if(event != null){
					var dataProvider = $j("#" + this.elements.target.attr("root")).attr("dataProvider");
					var options = aicommon.jsf.ajaxMenu.dataPool.__options[dataProvider];
					
					if(options && options.beforeHide)
						options.beforeHide.bind(this).call(event);
				}
				
				if(event == null || event.type != "mouseover")
					return true;
				
				var target = $j(event.target);
				if(target[0].tagName != "LI")target = target.parent();
				if(target[0] == this.elements.target[0])
					return false;
				else
					return true;
				
			},
			beforeDestroy : function(event){
				//把内部元素的qtip也销毁
				this.elements.content.find("li[childrenkey]").each(function(){
					var contentItem = $j(this);
					if(typeof contentItem.data("qtip") == 'object')
						contentItem.qtip("api").destroy();
				});
				this.elements.target.removeAttr("submenuinited");
				this.elements.target.removeAttr("menuinited");
			},
			beforeFocus : function(event){
				if(event == null)
					return true;
				
				var target = $j(event.target);
				if(!target.hasClass("menuMask") || target.parent().hasClass("current"))
					return false;
				else
					return true;
			}
		}
	});

};

//初始化子菜单
aicommon.jsf.ajaxMenu.initSubMenus = function(element,event,data){

	element = $j(element);
	element.parent().find("li").removeClass("current").removeClass("disabledCurrent");
	element.addClass("current");
	
	if(element.hasClass("disabled"))
		element.addClass("disabledCurrent");

	element.parent().find("li[id!='" + element.attr("id") + "'][childrenkey]").each(function(){
		aicommon.jsf.ajaxMenu.hideTips($j(this));
	});
	
	if(element.hasClass("disabled"))
		return;
	
	var id = element.attr("id") == element.attr("root") ? element.attr("root") + "_" : "";
	
	if(data != null && element.attr("submenuinited") != "true"){
		aicommon.jsf.ajaxMenu.replaceSubMenuContent(id + element.attr("id"),data);
	}
	else if(element.attr("childrenkey") != null && element.attr("submenuinited") != "true"){
		var dataProvider = $j("#" + element.attr("root")).attr("dataProvider");
		var cachedData = aicommon.jsf.ajaxMenu.dataPool[dataProvider];
		if(cachedData[element.attr("childrenkey")] == null){
			window[dataProvider](element.attr("childrenkey"),id + element.attr("id"));
		}
		else{
			aicommon.jsf.ajaxMenu.replaceSubMenuContent(id + element.attr("id"),
					cachedData[element.attr("childrenkey")]);
		}
	}
};

//每一层级菜单刚创建出来的时候是“正在加载”，数据加载后调用本方法
//把内容替换成最终的内容
aicommon.jsf.ajaxMenu.replaceSubMenuContent = function(id,data){
	var element = $j("#" + id);

	element.attr("submenuinited","true");
	
	if(element.attr("root") == null)
		element.attr("root",element.attr("id"));
	
	var dataProvider = $j("#" + element.attr("root")).attr("dataProvider");
	
	if(typeof data == 'string'){
		data = eval("(" + data + ")");
		aicommon.jsf.ajaxMenu.dataPool[dataProvider][data.key] = data;
	}
	
	var parentNode = $j("#" + id + "_submenus").parent();
	
	var menuData = $j.isArray(data) ? data : data.children;
	
	parentNode.html(aicommon.jsf.ajaxMenu.createSubMenuHtml(menuData,element).attr("id",id + "_submenus"));
	
	parentNode.find("li").attr("root",element.attr("root"));
	
	var options = aicommon.jsf.ajaxMenu.dataPool.__options[dataProvider];
	if(options.itemStyleClass)
		parentNode.find("li").addClass(options.itemStyleClass);
	
	if(options.styleClass)
		parentNode.find("ul").addClass(options.styleClass);
	
	element.qtip("api").elements.content.find("[childrenkey]").each(function(){
		var e = $j(this);
		aicommon.jsf.ajaxMenu.createMenu(this,{
			trigger : "mouseover",
			tipContent : aicommon.jsf.ajaxMenu.createLoading({
				id:e.attr("root") + "_" + e.attr("valuepath").replace(/\./g,"_") + "_submenus",
				styleClass : options.styleClass,
				itemStyleClass : options.itemStyleClass}),
			position : 'topRight'
		});
		e.append("<div class='arrow'></div>");
	});
	
};

//点击某个菜单的时候，设置值
aicommon.jsf.ajaxMenu.select = function(li){
	li = $j(li);
	//有些菜单不能作为最终的值
	if(li.attr("selectable") == "false"){
		//$j(li).qtip("api").show();
		return;
	}
	
	aicommon.jsf.ajaxMenu.hideTips(aicommon.jsf.ajaxMenu.getRoot(li));
	return li.triggerHandler("select");
};

//这个方法是设置值的一种方式，由菜单项的select事件触发，可以在后台的menuDataSupport中指定
aicommon.jsf.ajaxMenu.setValue = function(event){
	li = $j(this);
	
	var e = aicommon.jsf.ajaxMenu.getRoot(li);
	var id = e.parent().attr("id");
	var value = e.val();
	
	e.val(li.attr("namepath"));
	
	if("value" == e.attr("valueType"))
		e.next("input").val(li.attr("itemvalue"));
	else
		e.next("input").val(li.attr("valuepath"));

	var attrs = li.attrs();

	var hidden = e.next("input");
	
	var hiddenAttrs = hidden.attrs();
	
	for(var key in hiddenAttrs){
		if("type" != key && "value" != key && "id" != key && "name" != key && "style" != key && "class" != key){
			hidden.removeAttr(key);
		}
	}
	
	for(var key in attrs){
		if(/^attr\_.*/.test(key)){
			hidden.attr(key.replace("attr_",""),attrs[key]);
		}
	}
	
	e.triggerHandler("change");
};

//获取menu对象的触发元素
aicommon.jsf.ajaxMenu.getRoot = function(menu){
	return $j("#" + $j(menu).attr("root"));
};

//隐藏菜单
aicommon.jsf.ajaxMenu.hideTips = function(e){
	if(e.data("qtip") != null){
		e.qtip("api").hide();
		e.qtip("api").elements.content.find("li[childrenkey]").each(function(){
			aicommon.jsf.ajaxMenu.hideTips($j(this));
		});
	}
};

//根据数据创建一个层级的菜单html
aicommon.jsf.ajaxMenu.createSubMenuHtml = function(data,element){
	if(data.length == 0){
		var dataProvider = $j("#" + element.attr("root")).attr("dataProvider");
		var options = aicommon.jsf.ajaxMenu.dataPool.__options[dataProvider];
		var loading = aicommon.jsf.ajaxMenu.createLoading({id:element.attr("id") + "_submenus",styleClass : options.styleClass,content:'没有可用的子节点'});
		return $j(loading);
	}

	var result = $j("<ul class='ajaxMenu'></ul>");
	
	var namePath,valuePath,menu,onselect;
	
	for(var i=0;i<data.length;i++){
		if(data[i].rendered != null && !data[i].rendered(data[i],element))
			continue;
		
		if(element.attr("namepath") == null)
			namePath = data[i].name;
		else
			namePath = element.attr("namepath") + " - " + data[i].name;

		if(element.attr("valuepath") == null)
			valuePath = data[i].value;
		else
			valuePath = element.attr("valuepath") + "." + data[i].value;
		
		menu = $j("<li></li>")
			.attr("id",element.attr("root") + "_" + valuePath.replace(/\./g,"_"))
			.attr("namepath", namePath)
			.attr("valuepath", valuePath)
			.attr("itemvalue",data[i].value)
			.attr("selectable", data[i].selectable)
			.bind("select",data[i].onselect == null ? function(){} : data[i].onselect);
		
		menu.append($j("<div class='menuMask'>" + data[i].name + "</div>"));
		if(data[i].tip && data[i].tip != ""){
			var tip = $j("<div class='tipIcon'/>");
			tip.qtip({
				content : {
					text : data[i].tip
				},
				style : {
					"line-height" : "20px"
				}
			});
			menu.append(tip);
		}
		
		for(var key in data[i].attributes)
			menu.attr("attr_" + key,data[i].attributes[key]);
		
		if(data[i].childrenKey != null){
			menu.attr("childrenkey", data[i].childrenKey);
		}
		
		menu.bind(data[i].selectevent ? data[i].selectevent : "click",function(event){
			if(!$j(this).hasClass("disabled"))
				return aicommon.jsf.ajaxMenu.select(this,event);
		}).mouseover(function(event){
			aicommon.jsf.ajaxMenu.initSubMenus(this,event);
		});
		
		if(data[i].children){
			var dataProvider = $j("#" + element.attr("root")).attr("dataProvider");
			aicommon.jsf.ajaxMenu.dataPool[dataProvider][menu.attr("id") + "_children"] = data[i].children;
			menu.attr("childrenkey", menu.attr("id") + "_children");
		}

		if(typeof data[i].enabled == 'function'){
			menu.bind("show",data[i],function(event){
				if(!event.data.enabled(event))
					$j(this).addClass("disabled");
				else
					$j(this).removeClass("disabled");
			});
		}
		
		result.append(menu);
	}
	
	return result;
};

aicommon.jsf.ajaxMenu.createLoading = function(options){
	return "<ul class='ajaxMenu " + (options.styleClass == null ? "" : options.styleClass) + "' id='" + options.id + "'"
		+ (options.root == null ? "" : " root='" + options.root + "' ")
		+ "><li" + (options.itemStyleClass == null ? "" : "class='" + options.itemStyleClass + "' ")
		+ "><div class='menuMask'>" 
		+ (options.content || "正在加载子节点") + "</div></li></ul>";
};

/**
 * 销毁指定元素下的元素的qtip，默认销毁element下的全部元素的qtip
 * 
 * element 查找根
 * selector 查找的选择器
 */
aicommon.jsf.ajaxMenu.destroyMenus = function(element,selector){
	selector = selector || "[dataprovider],[childrenkey]";
	var owners;
	if(selector == "this")
		owners = element;
	else
		owners = $j(element).find(selector);
	
	owners.each(function(index,item){
		item = $j(item);
		if(item.data("qtip") == null)
			return;
		item.qtip("api").destroy();
	});
};